// File: jmcomic-core/src/main/java/dev/jukomu/common/base/logger/Logger.java
package dev.jukomu.common.base.logger;

import java.io.IOException;
import java.util.Collection;
import java.util.Set;
import java.util.function.Function;

/**
 * 对应Python的Logger，定义了基于Set的日志记录器通用接口。
 * 用于记录已处理或已存在的项，防止重复。
 *
 * @param <E> 记录器中元素的类型
 */
public interface Logger<E> extends Iterable<E> {

    /**
     * 检查指定元素是否已记录（已完成）。
     *
     * @param element 要检查的元素
     * @return 如果已记录返回 true
     */
    boolean isDone(E element);

    /**
     * 检查指定元素是否未记录（未完成）。
     *
     * @param element 要检查的元素
     * @return 如果未记录返回 true
     */
    default boolean isNotDone(E element) {
        return !isDone(element);
    }

    /**
     * 添加一个元素到记录器。
     *
     * @param element 要添加的元素
     * @param save    是否立即保存到持久化存储
     * @throws IOException 如果保存失败
     */
    void add(E element, boolean save) throws IOException;

    /**
     * 添加一个元素到记录器，不立即保存。
     *
     * @param element 要添加的元素
     * @throws IOException 如果添加失败
     */
    default void add(E element) throws IOException {
        add(element, false);
    }

    /**
     * 添加所有元素到记录器。
     *
     * @param elements 要添加的元素集合
     * @param save     是否立即保存到持久化存储
     * @throws IOException 如果保存失败
     */
    void addAll(Collection<E> elements, boolean save) throws IOException;

    /**
     * 添加所有元素到记录器，不立即保存。
     *
     * @param elements 要添加的元素集合
     * @throws IOException 如果添加失败
     */
    default void addAll(Collection<E> elements) throws IOException {
        addAll(elements, false);
    }

    /**
     * 获取记录器中元素的数量。
     *
     * @return 元素数量
     */
    int size();

    /**
     * 从记录器中移除一个元素。
     *
     * @param element 要移除的元素
     * @param save    是否立即保存到持久化存储
     * @throws IOException 如果保存失败
     */
    void remove(E element, boolean save) throws IOException;

    /**
     * 从记录器中移除一个元素，不立即保存。
     *
     * @param element 要移除的元素
     * @throws IOException 如果移除失败
     */
    default void remove(E element) throws IOException {
        remove(element, false);
    }

    /**
     * 设置内部数据Set。
     *
     * @param data 新的Set数据
     */
    void setData(Set<E> data);

    /**
     * 获取内部数据Set。
     *
     * @return 内部数据Set
     */
    Set<E> getData();

    /**
     * 清空记录器中的所有数据。
     */
    void clearData();

    /**
     * 从持久化存储加载数据。
     *
     * @throws IOException 如果加载失败
     */
    void load() throws IOException;

    /**
     * 保存数据到持久化存储。
     *
     * @param callback 保存前的回调函数，可以对数据进行处理
     * @return 保存后的数据（通常为Set）
     * @throws IOException 如果保存失败
     */
    Set<E> save(Function<Set<E>, Set<E>> callback) throws IOException;

    /**
     * 保存数据到持久化存储，不使用回调。
     *
     * @throws IOException 如果保存失败
     */
    default void save() throws IOException {
        save(null);
    }

    /**
     * 确保数据已从持久化存储加载。
     *
     * @throws IOException 如果加载失败
     */
    void makeSureLoaded() throws IOException;

    /**
     * 检查记录器是否包含指定元素。
     *
     * @param element 元素
     * @return 如果包含返回 true
     */
    boolean contains(E element);

    /**
     * 获取记录器中元素的数量。
     *
     * @return 数量
     */
    default int count() {
        return size();
    }
}